package com.jcp.baselibrary.base;

/**
 * Created by jcp on 2017/7/11.
 */

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;

import com.jcp.baselibrary.utils.DateUtil;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Date;

/**
 * =========================================================
 * @ProjectName: 
 * @ClassName: AppCrashException
 * @Description: 
 * @Author: jincp
 * @CreateDate: 2019/3/14 20:07
 * =========================================================
 */
public class AppCrashException implements UncaughtExceptionHandler {

    private static final AppCrashException mInstance = new AppCrashException();
    private UncaughtExceptionHandler mDefualtCrashHandler;
    private Context mContext;


    /**
     * 防止被重复创建
     */
    private AppCrashException() {}


    public static AppCrashException getInstance() {
        return mInstance;
    }

    public void init(Context context) {
        mContext = context.getApplicationContext(); // 确保获得的是系统级的Context
        mDefualtCrashHandler = Thread.getDefaultUncaughtExceptionHandler(); // 获取系统默认的异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this); // 把当前实例设置为系统默认异常处理器
    }


    /**
     * 这个方法是我们重写的重点，当系统出现未捕获异常时，就会调用这个方法
     *
     * @param t 出现未捕获异常的线程
     * @param e 未捕获的异常
     */
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        try {
            handleException(e);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        if (mDefualtCrashHandler != null) {
            //如果系统有默认异常处理就使用它处理
            mDefualtCrashHandler.uncaughtException(t, e);
        } else {
            //否则我们自行结束程序
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

    /**
     * 自定义错误处理，收集错误信息，发送错误报告等操作均在此完成
     *
     * @param ex
     * @return true：如果处理了该异常信息；否则返回 false
     */
    private boolean handleException(final Throwable ex) {
        if (ex == null) {
            return false;
        }
        //  如果用户不赋予外部存储卡的写权限导致的崩溃，会造成循环崩溃
        try {
            ex.printStackTrace();
            File crash = saveCrashInfo2File(ex);
            if (null != crash) {
                upLoadCrash(crash);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            // 使用 Toast 来显示异常信息
//            new Thread() {
//                @Override
//                public void run() {
//                    Looper.prepare();
//                    ToastUtils.show("很抱歉，程序出现异常，即将退出...");
//                    Looper.loop();
//                }
//            }.start();
        }
        return true;
    }

    private void upLoadCrash(final File crash) {

    }

    /**
     * 保存错误信息到文件中 *
     *
     * @param ex
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private File saveCrashInfo2File(Throwable ex) throws Exception {
        boolean append = false;
        File file = new File(BaseApplication.getAppCacheDir(), "crash.txt");
        if (System.currentTimeMillis() - file.lastModified() > 5000) {
            append = true;
        }
        PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(
                file, append)));
        // 导出发生异常的时间
        pw.println(DateUtil.formatDate(new Date()));
        // 导出手机信息
        collectDeviceInfo(pw);
        pw.println();
        // 导出异常的调用栈信息
        ex.printStackTrace(pw);
        pw.println();
        pw.close();
        return file;
    }

    /**
     * 收集设备参数信息
     *
     * @param pw
     */
    public void collectDeviceInfo(PrintWriter pw) throws PackageManager.NameNotFoundException {
        // 应用的版本名称和版本号
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(),
                PackageManager.GET_ACTIVITIES);
        pw.print("App Version: ");
        pw.print(pi.versionName);
        pw.print('_');
        pw.println(pi.versionCode);
        pw.println();

        // android版本号
        pw.print("OS Version: ");
        pw.print(Build.VERSION.RELEASE);
        pw.print("_");
        pw.println(Build.VERSION.SDK_INT);
        pw.println();

        // 手机制造商
        pw.print("Vendor: ");
        pw.println(Build.MANUFACTURER);
        pw.println();

        // 手机型号
        pw.print("Model: ");
        pw.println(Build.MODEL);
        pw.println();

        // cpu架构
        pw.print("CPU ABI: ");
        pw.println(Build.CPU_ABI);
        pw.println();

        pw.println();
    }
}
